<template>
	<el-table
		ref="table"
		v-loading="loading"
		:data="tableData"
		:stripe="stripe"
		border
		size="small"
		:height="height"
		:header-cell-style="{ height: '23px', lineHeight: '23px' }"
		:empty-text="emptyText"
		:show-summary="showSummary"
		:sum-text="sumText"
		:summary-method="summaryMethod"
		:row-style="rowStyle"
		:cell-style="cellStyle"
		@row-click="_rowClick"
		@row-dbclick="_rowDbclick"
	>
		<el-table-column
			v-if="_checkColumnIf(col)"
			v-for="(col, index) in computedColumns"
			:key="index"
			:prop="col.field"
			:label="col.label"
			:align="col.align || 'center'"
			:width="col.width"
			:fixed="col.fixed"
			:sortable="_getBooleanValue(col, 'sortable', false)"
			:show-overflow-tooltip="_getBooleanValue(col, 'showOverflowTooltip', true)"
		>
			<template slot="header" slot-scope="scope">
				<div v-if="col.hasOwnProperty('headers')" style="text-align: center;display: flex;">
					<div style="flex: 1;" v-for="(header, index) in col.headers" :key="index">
						<el-button
							v-if="header.name === 'Button'"
							:type="header.type"
							:icon="header.icon"
							:size="header.size || 'mini'"
							:round="_getBooleanValue(header, 'round', true)"
							@click="_tableHeaderTemplateHandleClick(scope, header)"
						>
							{{ header.label }}
						</el-button>

						<el-checkbox
							:disabled="checkedDisabled"
							v-else-if="header.name === 'CheckBox'"
							v-model="checkAll"
							:indeterminate="isIndeterminate"
							@change="_tableHeaderTemplateCheckBoxAll($event, scope, header)"
						>
							{{ header.label }}
						</el-checkbox>
						
						<span v-else>{{  header.label || col.label }}</span>
					</div>
				</div>

				<span v-else>{{ col.label }}</span>
			</template>

			<template slot-scope="scope">
				<div v-if="col.hasOwnProperty('templates')" :style="`display: flex;justify-content: ${col.align ? col.align : 'center'};align-items: center;`">
					<div style="display: inline-block;" v-for="(template, index) in col.templates" :key="index">
						<el-button
							style="margin: 0 2px;"
							v-if="template.name === 'Button' && _checkIf(scope.row, template)"
							:type="template.type"
							:icon="template.icon"
							:size="template.size || 'mini'"
							:round="_getBooleanValue(template, 'round', true)"
							@click="_tableColumnTemplateButtonClick(scope.row, template)"
						>
							{{ _fixedColumnLabel(scope.row, col, template) }}
						</el-button>

						<el-switch
							:disabled="template.disabled || false"
							v-else-if="template.name === 'Switch' && _checkIf(scope.row, template)"
							v-model="scope.row[col.field]"
							:active-value="template.activeValue"
							:inactive-value="template.inactiveValue"
							:active-text="template.activeText"
							:inactive-text="template.inactiveText"
							:active-color="template.activeColor || '#1890ff'"
							:inactive-color="template.inactiveColor || '#ff4949'"
							@change="_tableColumnTemplateSwitchChange($event, scope.row, template)"
						></el-switch>

						<el-checkbox
							:disabled="checkedDisabled"
							v-else-if="template.name === 'CheckBox' && _checkIf(scope.row, template)"
							v-model="scope.row[col.field || SELECTED_KEY]"
							@change="_tableColumnTemplateCheckBoxChange($event, scope.row, template)"
						>
							{{ _fixedColumnLabel(scope.row, col, template) }}
						</el-checkbox>
						
						<el-radio 
							v-model="selectedKey" 
							:label="scope.row[checkedKey]"
							:disabled="checkedDisabled"
							v-else-if="template.name === 'Radio' && _checkIf(scope.row, template)"
							@change="_tableColumnTemplateCheckBoxChange($event, scope.row, template)"
						>
							{{ _fixedColumnLabel(scope.row, col, template) }}
						</el-radio>

						<div
							v-for="(icon, index) in scope.row[col.field]"
							:key="index"
							v-else-if="template.name === 'Image' && _checkIf(scope.row, template)"
							style="display: inline-block;"
						>
							<el-tooltip style="vertical-align: middle;"
								:effect="template.tooltip ? template.tooltip.effect : 'dark'"
								:content="_tooltipContentFormatter(icon, col, template)"
								:disabled="!template.hasOwnProperty('tooltip') || icon[template.tooltip ? template.tooltip.contentField : 'content'] === ''"
								:placement="template.tooltip ? template.tooltip.placement : 'top'"
							>
								<el-image
									:style="{ width: template.width, height: template.height }"
									:src="icon[template.tooltip ? template.tooltip.srcField : 'src']"
									fit="contain"
								></el-image>
							</el-tooltip>
						</div>

						<div style="display: flex; justify-content: center; align-items: center;" v-else-if="template.name === 'Audio' && _checkIf(scope.row, template)">
							<audio style="min-width: 260px;height:24px;" controls :src="scope.row[col.field]">
								<!-- <source :src="scope.row[col.field]" type="audio/mpeg" />
								<source :src="scope.row[col.field]" type="audio/wav" />
								<source :src="scope.row[col.field]" type="audio/ogg" /> -->
							</audio>
						</div>
						
						<el-tooltip 
							v-else-if="_checkIf(scope.row, template)"
							style="vertical-align: middle;"
							:effect="template.tooltip ? template.tooltip.effect : 'dark'"
							:disabled="!template.hasOwnProperty('tooltip') || scope.row[template.tooltip ? template.tooltip.contentField : 'content'] === ''"
							:placement="template.tooltip ? template.tooltip.placement : 'top'"
						>
							<!-- :content="_tooltipContentFormatter(scope.row, col, template)" -->
							<div slot="content"><span v-html="_tooltipContentFormatter(scope.row, col, template)"></span></div>
							<span
								:style="_tableColumnTemplateHandleStyle2(scope.row, template)"
								@click="_tableColumnTemplateSpanClick(scope.row, template)"
							>
								{{ _tableColumnTemplateHandleText(scope.row, col, template) }}
							</span>
						</el-tooltip>
					</div>
				</div>

				<span v-else :style="_tableColumnTemplateHandleStyle1(scope.row, col)">{{ _fixedColumnValue(scope.row, col) }}</span>
			</template>
		</el-table-column>
	</el-table>
</template>

<script>
const CONSTANT_SELECTED_KEY = 'selected';

export default {
	props: {
		loading: {
			type: Boolean,
			default: false
		},
		emptyText: {
			type: String,
			default: '暂无数据'
		},
		watermark: {
			type: [String, Function],
			default: null
		},
		height: {
			type: [Number, String],
			default: 200
		},
		columns: {
			type: Array,
			default() {
				return [];
			}
		},
		checked: {
			type: Boolean,
			default: false
		},
		checkedKey: {
			type: String,
			default: 'id'
		},
		checkedValue: {
			type: [ String, Number ],
			default: null
		},
		checkedDisabled: {
			type: Boolean,
			default: false
		},
		checkedMultiple: {
			type: Boolean,
			default: true
		},
		checkedChange: {
			type: Function,
			default: null
		},
		clickChecked: {
			type: Boolean,
			default: true
		},
		dbclickChecked: {
			type: Boolean,
			default: false
		},
		showSummary: {
			type: Boolean,
			default: false
		},
		sumText: {
			type: String,
			default: '合计'
		},
		summaryMethod: {
			type: Function,
			default: null
		},
		stripe: {
			type: Boolean,
			default: true
		},
		rowStyle: {
			type: [Function, Object],
			default: null
		},
		cellStyle: {
			type: [Function, Object],
			default: null
		},
		data: {
			type: Array,
			default() {
				return [];
			}
		}
	},
	data() {
		return {
			checkAll: false,
			isIndeterminate: false,
			tableData: [],
			SELECTED_KEY: CONSTANT_SELECTED_KEY,
			selectedRows: [],
			selectedKeys: [],
			selectedRow: {},
			selectedKey: '',
			preSelectedKey: ''
		};
	},
	created() {},
	mounted() {
		let text = '';
		if (this._isString(this.watermark)) {
			text = this.watermark;
		}
		if (this._isFunction(this.watermark)) {
			text = this.watermark();
		}
		this.$refs.table.$el.style.backgroundImage = `url('${this._textToImage(text)}')`;
	},
	computed: {
		computedColumns() {
			let result = [];
			if (this.checked) {
				if(this.checkedMultiple) {
					result.push({
						field: CONSTANT_SELECTED_KEY,
						width: 50,
						fixed: true,
						headers: [
							{
								name: 'CheckBox',
								change: this._checkedHeaderChange
							}
						],
						templates: [
							{
								name: 'CheckBox',
								change: this._checkedColumnChange
							}
						]
					});
				} else {
					result.push({
						field: CONSTANT_SELECTED_KEY,
						label: '选择',
						width: 50,
						fixed: true,
						templates: [
							{
								name: 'Radio',
								change: this._checkedColumnChange
							}
						]
					});
				}
			}
			this.columns.forEach(col => {
				result.push(col);
			});
			return result;
		}
	},
	watch: {
		// checked() {
		// 	this._returnColumns();
		// 	this.$nextTick(() => {
		// 		this.$refs.eltable.doLayout();
		// 	});
		// },
		// selectedRows: {
		// 	handler(newVal, oldVal) {
		// 		let count = 0;
		// 		this.tableData.forEach(td => {
		// 			if(td[this.SELECTED_KEY]) {
		// 				count++;
		// 			}
		// 		})
		// 		this.checkAll = ( this.tableData.length === count );
		// 		this.isIndeterminate = ( this.tableData.length >= count && count > 0 );
		// 		// this.checkAll = ( this.tableData.length === this.selectedRows.length );
		// 		// this.isIndeterminate = ( this.tableData.length !== this.selectedRows.length && this.selectedRows.length > 0 );
		// 	},
		// 	deep: false,
		// 	immediate: false
		// },
		data: {
			handler(newVal, oldVal) {
				if(newVal) {
					this.tableData = this._clone(newVal);
					if(this.tableData.length) {
						if (this.checked) {
							if(this.checkedMultiple) {
								this.tableData.forEach(td => {
									if (!td[this.checkedKey]) {
										throw new Error('CuteTable:checkedKey不匹配');
									}
									let find = false;
									this.selectedRows.forEach(srow => {
										if (srow[this.checkedKey] === td[this.checkedKey]) {
											this.$set(td, this.SELECTED_KEY, true);
											find = true;
										}
									});
									if (!find) {
										this.$set(td, this.SELECTED_KEY, false);
									}
								});
								this._checkAllStatus();
							} else {
								if(this.checkedValue) {
									for(let i = 0; i < this.tableData.length; i++) {
										const td = this.tableData[i];
										if(td[this.checkedKey] === this.checkedValue) {
											this.selectedRow = td;
											break;
										}
									}
								} else {
									this.selectedRow = this.tableData[0];
								}
								this.selectedKey = this.selectedRow[this.checkedKey];
								this.preSelectedKey = this.selectedKey;
							}
						}
					}
				}
			},
			deep: false,
			immediate: true
		}
	},
	methods: {
		_isString(str) {
			return typeof str == 'string' && str.constructor == String;
		},
		_isFunction(obj) {
			return typeof obj == 'function' && obj.constructor == Function;
		},
		_textToImage(text = 'watermark', fontsize = 40, fontcolor = 'rgba(0,0,0,0.1)') {
			const cwidth = 384; //window.screen.width;
			const cheight = 230;
			const canvas = document.createElement('canvas');
			canvas.width = cwidth;
			canvas.height = cheight;
			const ctx = canvas.getContext('2d');
			ctx.rotate(-Math.PI / 6);
			ctx.translate(-85, 85);
			ctx.font = fontsize + 'px Microsoft Yahei';
			ctx.fillStyle = fontcolor;
			ctx.textBaseline = 'top';
			const textWidth = ctx.measureText(text).width;
			ctx.fillText(text, (cwidth - textWidth) * 0.5, (cheight - fontsize) * 0.5);
			return canvas.toDataURL('image/png');
		},
		_getBooleanValue(item, field, val) {
			if(item.hasOwnProperty(field)) {
				if(this._isFunction(item[field])) {
					return item[field]();
				}
				return item[field]
			}
			// if(item.hasOwnProperty('component') && item.component.hasOwnProperty(field)) {
			// 	if(this._isFunction(item.component[field])) {
			// 		return item.component[field]();
			// 	}
			// 	return item.component[field]
			// }
			return val
		},
		_rowClick(row, column, event) {
			if (this.checked && this.clickChecked) {
				this._checkedSelected(row);
			}
			this.$emit('rowClick', { row, column, event })
		},
		_rowDbclick(row, column, event) {
			if (this.checked && this.dbclickChecked) {
				this._checkedSelected(row);
			}
			this.$emit('rowDbclick', { row, column, event })
		},
		_fixedColumnLabel(row, col, template) {
			if (col && col.formatter) {
				return col.formatter(this.dataProvider, row, col);
			}
			if (col && col.labelFormatter) {
				return col.labelFormatter(row, col);
			}
			return template.label;
		},
		_fixedColumnValue(row, col) {
			if (col && col.formatter) {
				return col.formatter(this.dataProvider, row, col);
			}
			if (col && col.textFormatter) {
				return col.textFormatter(row, col);
			}
			return row[col.field];
		},
		_tableHeaderTemplateHandleClick(scope, header) {
			if (header && header.click) {
				header.click(scope, header);
			}
		},
		_tableHeaderTemplateCheckBoxAll(check, scope, header) {
			if (header && header.change) {
				header.change(check, scope, header);
			}
		},
		_tableColumnTemplateButtonClick(row, template) {
			if (template && template.click) {
				template.click(row);
			}
		},
		_tableColumnTemplateSwitchChange(check, row, template) {
			if (template && template.change) {
				template.change(check, row);
			}
		},
		_tableColumnTemplateCheckBoxChange(check, row, template) {
			if (template && template.change) {
				template.change(check, row);
			}
		},
		_tableColumnTemplateSpanClick(row, template) {
			if (template && template.click) {
				template.click(row);
			}
		},
		_tableColumnTemplateHandleStyle1(row, col) {
			if (col && col.styleFormatter) {
				return col.styleFormatter(row, col);
			}
			return {};
		},
		_tableColumnTemplateHandleStyle2(row, template) {
			if (template && template.styleFormatter) {
				return template.styleFormatter(row, template);
			}
			return {};
		},
		_tableColumnTemplateHandleText(row, col, template) {
			if (template && template.textFormatter) {
				return template.textFormatter(row, col, template);
			}
			// if(row.hasOwnProperty(col.field) && row[col.field]) {
			// 	return row[col.field];
			// }
			return '-';
		},
		_tooltipContentFormatter(row, col, template) {
			if (template.tooltip && template.tooltip.textFormatter) {
				return template.tooltip.textFormatter(row, col, template);
			}
			return row[template.tooltip ? template.tooltip.contentField : 'content'];
		},
		_checkColumnIf(col) {
			if (col && col.validator) {
				return col.validator(col);
			}
			return true;
		},
		_checkIf(row, template) {
			if (template && template.validator) {
				return template.validator(row);
			}
			return true;
		},
		_checkedHeaderChange(check, scope, header) {
			// console.log(check);
			// console.log(scope);
			// console.log(header);
			this.tableData.forEach(td => {
				td.selected = check;
				const index = this.selectedRows.findIndex(srow => {
					return srow[this.checkedKey] === td[this.checkedKey];
				});
				if (check) {
					if (index === -1) {
						this.selectedRows.push(td);
						this.selectedKeys.push(td[this.checkedKey]);
					}
				} else {
					this.selectedRows.splice(index, 1);
					this.selectedKeys.splice(index, 1);
				}
			});
			this.isIndeterminate = false;
		},
		_checkedColumnChange(check, row) {
			if(this.checkedMultiple) {
				if (check) {
					this.selectedRows.push(row);
					this.selectedKeys.push(row[this.checkedKey]);
				} else {
					const index = this.selectedRows.findIndex(srow => {
						return srow[this.checkedKey] === row[this.checkedKey];
					});
					this.selectedRows.splice(index, 1);
					this.selectedKeys.splice(index, 1);
				}
				this._checkAllStatus();
			} else {
				this.selectedRow = row;
				this.selectedKey = row[this.checkedKey];
			}
			if(this.checkedChange) {
				this.checkedChange(
					this.getSelectedRows(),
					this.getSelectedKeys()
				);
			}
		},
		_checkAllStatus() {
			let count = 0;
			this.tableData.forEach(td => {
				if (td[this.SELECTED_KEY]) {
					count++;
				}
			});
			this.checkAll = this.tableData.length === count;
			this.isIndeterminate = this.tableData.length > count && count > 0;
		},
		_checkedSelected(row) {
			if(this.checkedMultiple) {
				// 多选时暂时没加入点击行选中
				// if (check) {
				// 	this.selectedRows.push(row);
				// 	this.selectedKeys.push(row[this.checkedKey]);
				// } else {
				// 	const index = this.selectedRows.findIndex(srow => {
				// 		return srow[this.checkedKey] === row[this.checkedKey];
				// 	});
				// 	this.selectedRows.splice(index, 1);
				// 	this.selectedKeys.splice(index, 1);
				// }
				// this._checkAllStatus();
			} else {
				this.selectedRow = row;
				this.selectedKey = row[this.checkedKey];
				
				if(this.preSelectedKey !== this.selectedKey) {
					this.preSelectedKey = this.selectedKey;
					if(this.checkedChange) {
						this.checkedChange(
							this.getSelectedRows(),
							this.getSelectedKeys()
						);
					}
				}
			}
		},
		_clone(ds) {
			let result = [];
			ds.forEach(d => {
				let item = {};
				for (let key in d) {
					item[key] = d[key];
				}
				result.push(item);
			});
			return result;
		},
		//
		//PUBLIC METHODS
		//
		getSelectedRows() {
			if(this.checkedMultiple) {
				return this.selectedRows;
			} else {
				return this.selectedRow;
			}
		},
		getSelectedKeys() {
			if(this.checkedMultiple) {
				return this.selectedKeys;
			} else {
				return this.selectedKey;
			}
		},
		setCheckedValue(value) {
			for(let i = 0; i < this.tableData.length; i++) {
				const td = this.tableData[i];
				if(td[this.checkedKey] === value) {
					this.selectedRow = td;
					break;
				}
			}
			this.selectedKey = this.selectedRow[this.checkedKey];
			this.preSelectedKey = this.selectedKey;
		},
		resetSelected() {
			this.selectedRows = [];
			this.selectedKeys = [];
			this.selectedRow = {};
			this.selectedKey = '';
		}
	}
};
</script>

<style lang="scss" scoped>
::v-deep {
	.el-checkbox__label {
		padding-left: 0px;
	}
	
	.el-radio__label {
		padding-left: 0px;
	}
	
	.el-switch .el-switch__label {
		text-align: left;
	}
}
</style>
